!! Copyright (C) 2009,2010,2011,2012  Marco Restelli
!!
!! This file is part of:
!!   FEMilaro -- Finite Element Method toolkit
!!
!! FEMilaro is free software; you can redistribute it and/or modify it
!! under the terms of the GNU General Public License as published by
!! the Free Software Foundation; either version 3 of the License, or
!! (at your option) any later version.
!!
!! FEMilaro is distributed in the hope that it will be useful, but
!! WITHOUT ANY WARRANTY; without even the implied warranty of
!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
!! General Public License for more details.
!!
!! You should have received a copy of the GNU General Public License
!! along with FEMilaro; If not, see <http://www.gnu.org/licenses/>.
!!
!! author: Marco Restelli                   <marco.restelli@gmail.com>

!>\brief
!!
!! Dummy version of \c mod_mumpsintf to avoid linking MUMPS.
!!
!! \n
!!
!! The constructor, destructor and clean functions can be called,
!! while the remaining functions return an error. The use statements
!! are the same as in the true module, to simplify debugging and
!! testing with and without MUMPS.
!<----------------------------------------------------------------------
module mod_mumpsintf

!-----------------------------------------------------------------------

 use mod_utils, only: &
   t_realtime, my_second

 use mod_messages, only: &
   mod_messages_initialized, &
   error,   &
   warning, &
   info

 use mod_kinds, only: &
   mod_kinds_initialized, &
   wp

 use mod_sparse, only: &
   mod_sparse_initialized, &
   ! sparse types
   t_col, t_tri,&
   col2tri,     &
   clear

 use mod_mpi_utils, only: &
   mod_mpi_utils_initialized, &
   mpi_reduce, wp_mpi, mpi_sum, &
   mpi_bcast

 use mod_state_vars, only: &
   mod_state_vars_initialized, &
   c_stv

 use mod_output_control, only: &
   mod_output_control_initialized, &
   elapsed_format, base_name

 use mod_linsolver_base, only: &
   mod_linsolver_base_initialized, &
   c_linpb

!-----------------------------------------------------------------------
 
 implicit none

!-----------------------------------------------------------------------

! Module interface

 public :: &
   mod_mumpsintf_constructor, &
   mod_mumpsintf_destructor,  &
   mod_mumpsintf_initialized, &
   c_mumpspb

 private

!-----------------------------------------------------------------------

 type dmumps_struc
   ! For real MUMPS, this type is defined in dmumps_struc.h
 end type dmumps_struc

 type, extends(c_linpb), abstract :: c_mumpspb
  logical :: distributed
  integer :: poo = -1
  integer :: gn
  type(t_col), pointer :: m
  real(wp), pointer :: rhs(:)
  integer, pointer :: gij(:)
  logical :: transposed_mat = .false.
  integer :: mpi_comm
  integer, allocatable, private :: l2g_map(:)
  type(dmumps_struc), private :: mumps_par
  logical, private :: sys_set = .false.
 contains
  procedure, pass(s) :: factor => mumps_factor
  procedure, pass(s) :: solve  => mumps_solve
  procedure, pass(s) :: clean  => mumps_clean
  procedure, nopass :: working_implementation => mumps_wi
  procedure(i_xassign), deferred, pass(s) :: xassign
 end type c_mumpspb

 abstract interface
  subroutine i_xassign(x,s,mumps_x)
   import :: wp, c_stv, c_mumpspb
   implicit none
   real(wp),         intent(in) :: mumps_x(:)
   class(c_mumpspb), intent(inout) :: s
   class(c_stv),     intent(inout) :: x
  end subroutine i_xassign
 end interface

 logical, protected :: &
   mod_mumpsintf_initialized = .false.
 character(len=*), parameter :: &
   errormsg = &
     'This is not a real MUMPS interface and should not be called.'
 character(len=*), parameter :: &
   this_mod_name = 'mod_mumpsintf_dummy'

!-----------------------------------------------------------------------

contains

!-----------------------------------------------------------------------

 subroutine mod_mumpsintf_constructor()
  character(len=*), parameter :: &
    this_sub_name = 'constructor'

   !Consistency checks ---------------------------
   if( (mod_messages_initialized.eqv..false.) .or. &
          (mod_kinds_initialized.eqv..false.) .or. &
         (mod_sparse_initialized.eqv..false.) .or. &
      (mod_mpi_utils_initialized.eqv..false.) .or. &
 (mod_output_control_initialized.eqv..false.) .or. &
 (mod_linsolver_base_initialized.eqv..false.) ) then
     call error(this_sub_name,this_mod_name, &
                'Not all the required modules are initialized.')
   endif
   if(mod_mumpsintf_initialized.eqv..true.) then
     call warning(this_sub_name,this_mod_name, &
                  'Module is already initialized.')
   endif
   !----------------------------------------------

   mod_mumpsintf_initialized = .true.
 end subroutine mod_mumpsintf_constructor

!-----------------------------------------------------------------------
 
 subroutine mod_mumpsintf_destructor()
  character(len=*), parameter :: &
    this_sub_name = 'destructor'
   
   !Consistency checks ---------------------------
   if(mod_mumpsintf_initialized.eqv..false.) then
     call error(this_sub_name,this_mod_name, &
                'This module is not initialized.')
   endif
   !----------------------------------------------

   mod_mumpsintf_initialized = .false.
 end subroutine mod_mumpsintf_destructor

!-----------------------------------------------------------------------

  pure function mumps_wi()
   logical :: mumps_wi
    mumps_wi = .false.
  end function mumps_wi

!-----------------------------------------------------------------------

 subroutine mumps_factor(s,phase)
  class(c_mumpspb), intent(inout) :: s
  character(len=*), intent(in), optional :: phase
 
  character(len=*), parameter :: &
    this_sub_name = 'mumps_factor'

   call error(this_sub_name,this_mod_name,errormsg)
 
 end subroutine mumps_factor
 
!-----------------------------------------------------------------------
 
 subroutine mumps_solve(x,s)
  class(c_mumpspb), intent(inout) :: s
  class(c_stv),     intent(inout) :: x

  character(len=*), parameter :: &
    this_sub_name = 'mumps_solve'

   call error(this_sub_name,this_mod_name,errormsg)
 
 end subroutine mumps_solve
 
!-----------------------------------------------------------------------
 
 subroutine mumps_clean(s)
  class(c_mumpspb), intent(inout) :: s

  character(len=*), parameter :: &
    this_sub_name = 'mumps_clean'

   ! nothing to do
 
 end subroutine mumps_clean
 
!-----------------------------------------------------------------------

end module mod_mumpsintf

